package proxy;

import org.springframework.cglib.core.DebuggingClassWriter;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import prototype.Person;

import java.lang.reflect.Method;

/**
 * 静态代理手动拿到目标对象，构造注入，手动调用代理对象方法；
 * 动态代理自动注入，生成一个新的对象
 * 实现功能增强，保护目标对象
 * cglib采用继承父类的方式
 * jdk采用实现接口的方式，要求代理对象实现接口
 * 思想：都是通过生成字节码，重组成一个新的类
 * jdkProxy 对接口依赖更强，逻辑效率低，生成逻辑简单，使用反射
 * cglibProxy对目标类没有任何要求，效率更高，底层没有用到反射，不能有final修饰符
 * Spring中当Bean有实现接口时，选用JDK动态代理
 * 当Bean没有实现接口时，选用Cglib
 * 可添加<aop:aspectj-autoproxy proxy-target-class="true"/>强制使用cglib实现动态代理
 * 应用场景 aop,日志监控，动态数据源切换，分库分表，权限控制等等
 */
public class CGLIBProxy implements MethodInterceptor {
    public Object getInstance(Class<?> clazz){
        Enhancer enhancer=new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }
    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        before();
        Object result=methodProxy.invokeSuper(o,objects);
        after();
        return result;
    }

    private void after() {
        System.out.println("test");
    }

    private void before() {
    }

    public static void main(String[] args) {
        System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"E://cglib");
        CGLIBProxy cglibProxy=new CGLIBProxy();
        GunDog object= (GunDog) cglibProxy.getInstance(GunDog.class);
        object.run();
    }
}
